package com.yuandian.management.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yuandian.api.management.entity.ConfGraph;
import com.yuandian.api.management.entity.ConfNodeProperty;
import com.yuandian.api.management.entity.ConfSegment;
import com.yuandian.api.management.entity.ConfSystem;
import com.yuandian.api.management.enums.GraphType;
import com.yuandian.api.management.vo.AllSystemItRoadNodeVo;
import com.yuandian.management.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 告警信息-Service实现
 * @author zfsn
 * @date 2023-4-4
 */
@Service
@RequiredArgsConstructor
public class ConfAllSystemItRoadServiceImpl implements ConfAllSystemItRoadService {

	private final ConfNodePropertyService confNodePropertyService;

	private final ConfSystemService confSystemService;

	private final ConfSegmentService confSegmentService;

	private final ConfGraphService confGraphService;

	/**
	 * 全系统IT路径图
	 *
	 * @return 通用返回对象
	 */
	@Override
	public List<AllSystemItRoadNodeVo> getAllItRoadGraph() {

		// 1. 获取全系统各个网端的位置信息
		LambdaQueryWrapper<ConfNodeProperty> propertyLambdaQueryWrapper = Wrappers.lambdaQuery();
		propertyLambdaQueryWrapper.eq(ConfNodeProperty::getType, GraphType.ALL_IT_ROAD_RELATIONSHIP.getType());
		propertyLambdaQueryWrapper.eq(ConfNodeProperty::getGraphId, 0);
		Map<String, ConfNodeProperty> segmentPositionMap = confNodePropertyService.list(propertyLambdaQueryWrapper).stream().collect(Collectors.toMap(ConfNodeProperty::getNodeId, k -> k, (k1, k2) -> k1));

		// 2. 获取监控中, 且不为虚拟系统的应用系统
		LambdaQueryWrapper<ConfSystem> systemLambdaQueryWrapper = Wrappers.lambdaQuery();
		systemLambdaQueryWrapper.eq(ConfSystem::getStatus, 1);
		systemLambdaQueryWrapper.eq(ConfSystem::getIsVirtual, 0);
		List<ConfSystem> confSystems = confSystemService.list(systemLambdaQueryWrapper);
		if (confSystems.size() == 0){
			return new ArrayList<>();
		}

		List<AllSystemItRoadNodeVo> treeNodes = new ArrayList<>();
		for (ConfSystem confSystem : confSystems) {
			LambdaQueryWrapper<ConfSegment> confSegmentLambdaQueryWrapper = Wrappers.lambdaQuery();
			confSegmentLambdaQueryWrapper.in(ConfSegment::getSystemId, confSystem.getId());
			List<ConfSegment> confSegments = confSegmentService.list(confSegmentLambdaQueryWrapper);

			LambdaQueryWrapper<ConfGraph> confGraphLambdaQueryWrapper = Wrappers.lambdaQuery();
			confGraphLambdaQueryWrapper.eq(ConfGraph::getType, GraphType.IT_ROAD_RELATIONSHIP.getType());
			confGraphLambdaQueryWrapper.eq(ConfGraph::getGraphId, confSystem.getId());
			List<ConfGraph> confGraphs = confGraphService.list(confGraphLambdaQueryWrapper);


			Set<String> headNodes = new HashSet<>();
			Map<String, AllSystemItRoadNodeVo> map = new HashMap<>();
			List<String> parentNodeIds = confGraphs.stream().map(ConfGraph::getParentNodeId).collect(Collectors.toList());
			for (ConfGraph node : confGraphs) {
				// 找出根节点
				if (!parentNodeIds.contains(node.getNodeId())) {
					headNodes.add(node.getParentNodeId());
				}
				String prev = node.getParentNodeId();
				String cur = node.getNodeId();

				AllSystemItRoadNodeVo treeNode = map.getOrDefault(cur, getTreeNodeInfo(segmentPositionMap, confSegments, cur));
				AllSystemItRoadNodeVo parentNode = map.getOrDefault(prev, getTreeNodeInfo(segmentPositionMap, confSegments, prev));
				parentNode.getChildNodes().add(treeNode);
				map.put(prev, parentNode);
				map.put(cur, treeNode);
			}

			for (String headNode : headNodes) {
				treeNodes.add(map.get(headNode));
			}
		}
		return treeNodes;
	}

	/**
	 * 填充树节点数据
	 * @param segmentPositionMap
	 * @param confSegments
	 * @param cur
	 * @return
	 */
	private AllSystemItRoadNodeVo getTreeNodeInfo(Map<String, ConfNodeProperty> segmentPositionMap, List<ConfSegment> confSegments, String cur) {
		Map<Integer, ConfSegment> confSegmentMap = confSegments.stream().collect(Collectors.toMap(ConfSegment::getId, k -> k, (k1, k2) -> k1));
		AllSystemItRoadNodeVo allSystemItRoadNodeVo = new AllSystemItRoadNodeVo();
		allSystemItRoadNodeVo.setId(Integer.valueOf(cur));
		allSystemItRoadNodeVo.setNodeId(cur);

		if (confSegmentMap.containsKey(Integer.valueOf(cur))) {
			allSystemItRoadNodeVo.setType(confSegmentMap.get(Integer.valueOf(cur)).getType());
			allSystemItRoadNodeVo.setSystemId(confSegmentMap.get(Integer.valueOf(cur)).getSystemId());
		}
		if (segmentPositionMap.containsKey(cur)) {
			allSystemItRoadNodeVo.setLocationX(segmentPositionMap.get(cur).getLocationX());
			allSystemItRoadNodeVo.setLocationY(segmentPositionMap.get(cur).getLocationY());
		}
		return allSystemItRoadNodeVo;
	}
}